﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using PLAYXPERT.Interfaces;
using PLAYXPERT.Widgets;
using SkypePXP;
using SkypePXP.Properties;

namespace Widgets.SkypePXP
{
    /// <summary>
    /// Main interfaces to PLAYXPERT
    /// </summary>
    /// <remarks>
    /// You should customize this file to your own liking: widget icon, name, etc., etc.
    /// </remarks>
    public class SkypePXP : IWidget, IDockItem
    {
        #region Implementation of IWidget

        /// <summary>
        /// Gets the widget name
        /// </summary>
        /// <returns>
        /// The widget name string
        /// </returns>
        public string GetWidgetName()
        {
            return "SkypePXP";
        }

        /// <summary>
        ///             Get the widget GUID that uniquely identifies the widget
        /// </summary>
        /// <returns>
        /// A GUID. If another widget with this GUID is already loaded, 
        ///             this widget will be ignored.
        /// </returns>
        public Guid GetWidgetGUID()
        {
            var guidAttribute = (GuidAttribute)
                GetFirstAssemblyAttribute(typeof(GuidAttribute));

            return new Guid(guidAttribute.Value);
        }

        /// <summary>
        /// Get the widget author’s name
        /// </summary>
        /// <returns>
        /// A string representing author’s name. Can be left blank
        /// </returns>
        public string GetWidgetAuthor()
        {
            return string.Empty;
        }

        /// <summary>
        /// Get the widget company’s name
        /// </summary>
        /// <returns>
        /// A string representing the company name. Can be left blank
        /// </returns>
        public string GetWidgetCompany()
        {
            var companyAttribute = (AssemblyCompanyAttribute)
                GetFirstAssemblyAttribute(typeof(AssemblyCompanyAttribute));

            return companyAttribute.Company;
        }

        /// <summary>
        ///             Gets the information widget website. The website could include a 
        ///             widget community. 
        /// </summary>
        /// <returns>
        /// The address for the widget website. Can be left blank
        /// </returns>
        public string GetWidgetWebsite()
        {
            return string.Empty;
        }

        /// <summary>
        ///             Gets the .Net Assembly version string
        /// </summary>
        /// <returns>
        /// Version string. Must be in .Net standard format. If left 
        ///             blank, an exception will be thrown. 
        /// </returns>
        public Version GetWidgetVersion()
        {
            var versionAttribute = (AssemblyVersionAttribute)
                GetFirstAssemblyAttribute(typeof(AssemblyVersionAttribute));

            return new Version(versionAttribute.Version);
        }

        /// <summary>
        /// Obsolete method - will be removed no later than PXP 1.1
        /// </summary>
        public string GetWidgetURL()
        {
            return string.Empty;
        }

        /// <summary>
        ///             Gets a list of features that the widget supports. See further 
        ///             documentation on the feature strings for core features. This list 
        ///             is used by feature loaders to do further processing.
        /// </summary>
        /// <returns>
        /// A list of features that the widget supports. Returning 
        ///             null means the widget only implements the IWidget interface.
        /// </returns>
        public List<string> GetWidgetFeatures()
        {
            return Features;
        }

        public List<string> Features
        {
            get
            {
                if (features == null)
                {
                    features = new List<string>
                        {
                            // Our widget provides a DockItem
                            "Dock",
                            
                            // Our widget has a Settings Page, that can 
                            // be shown in the preferences dialog
                            //"SettingsPage",
                        };
                }
                return features;
            }
        }

        private List<string> features;


        /// <summary>
        /// Called by the SkypePXP Manager to get an instance of a feature provided by a widget.  
        /// In most cases, the widget should return an implementation of a well known 
        /// interface like ISettingsPage.
        /// </summary>
        /// <param name="featureName">the name of the feature to get. Example: “SettingsPage”</param>
        /// <returns>
        /// An instance of the feature. Example: an implementation of ISettingsPage.
        /// </returns>
        public object GetFeatureInstance(string featureName)
        {
            object result = null;

            /// Since this class implements interfaces for the "Dock" feature, 
            /// we simply return this instance for those features.  For the SettingsPage 
            /// feature, we return an instance of a class that implements ISettingsPage.
            switch (featureName)
            {
                // Return the class that implements the IDockItem interface
                case "Dock":
                    result = this;
                    break;
                // Return the class that implements the ISettingsPage interface
                case "SettingsPage":
                    result = SettingsPage;
                    break;
            }
            return result;
        }

        /// <summary>
        ///             Called by the widget manager to initialize the widget. An instance 
        ///             of the core is passed to the widget to allow the widget to access 
        ///             core components
        /// </summary>
        /// <param name="core">The core instance</param>
        /// <param name="data">Initialization data - not needed for external widgets.</param>
        public void OnLoad(ICore core, string data)
        {
            // core is used to get interfaces to various services offered by the PXP platform.
            _core = core;
            
        }

        /// <summary>
        ///             Called by the widget manager to inform the widget that it is being 
        ///             unloaded. If the widget is not stopped, the widget should stop itself. 
        /// </summary>
        /// <param name="data"></param>
        public void OnUnload(string data)
        {
            /// Dispose of all objects, or let the Garbage Collector get them.
            /// Connections to all external resources should have already been 
            /// broken, in OnStop()


        }

        /// <summary>
        ///             Called by the widget manager after the widget is loaded. The widget 
        ///             should not start any work until this method is invoked. This is to 
        ///             prevent dependency problems where a certain core component has not yet loaded.
        /// </summary>
        public void OnStart()
        {
            /// Begin creating connections to all connections to external 
            /// resources (databases, network connections, etc, etc) 
            /// This is best done in a background thread, so the user doesn't see 
            /// "Loading widget: YourWidget" for a long time :)
            widgetMainForm = new MainForm(_core);
        }

        /// <summary>
        /// Called by the widget manager. Instruction to stop work gracefully. 
        /// </summary>
        /// <remarks>
        /// Receiving a stop does not indicate that the widget will be 
        /// unloaded. The widget could be restarted. 
        /// </remarks>
        public void OnStop()
        {
            /// Cut connections to all external resources (databases, network connections, 
            /// etc, etc)
            /// 
            /// All connections should be cut in this thread, before returning from this call.
        }

        #endregion

        #region Implementation of IDockItem

        /// <summary>
        /// Get the current text to be displayed by the dock manager
        /// </summary>
        /// <returns>
        /// String of text to be painted by IDock
        /// </returns>
        public string GetText()
        {
            return "Skype For Power Gamers";
        }

        /// <summary>
        /// Get the current image to be displayed by the dock manager
        /// </summary>
        /// <returns>
        /// Image be painted by IDock
        /// </returns>
        public Image GetImage(string state)
        {
            // We can return an image based on wether the mouse cursor is over the dock item or not.
            switch (state)
            {
                case "over_icon":
                    return Resources.DockIconOver;
                case "normal_icon":
                default:
                    return Resources.DockIcon;
            }
        }

        /// <summary>
        ///             Get the menu item for the dock item. This menu will be displayed 
        ///             by the dock as the dock item context menu.
        /// </summary>
        /// <returns>
        /// The menu to be displayed by the dock as the dock item context menu
        /// </returns>
        public ToolStripMenuItem GetContextMenuItem()
        {
            return null;
        }

        /// <summary>
        ///             Called by the dock manager to inform the dock item of a mouse down event
        /// </summary>
        /// <param name="e">MouseEventArgs data passed down from the dock manager</param>
        public void OnMouseDown(MouseEventArgs e)
        {

            // Create our main form and show it for the user.
            
        }

        /// <summary>
        /// Called by the dock manager to inform the dock item of a mouse up event
        /// </summary>
        /// <param name="e">MouseEventArgs data passed down from the dock manager</param>
        public void OnMouseUp(MouseEventArgs e)
        {
            WidgetMainForm.TopMost = true;
            WidgetMainForm.Focus();
            WidgetMainForm.BringToFront();
            WidgetMainForm.TopMost = false;
            WidgetMainForm.Show();
        }

        /// <summary>
        /// Called by the dock manager to inform the dock item of a mouse move event
        /// </summary>
        /// <remarks>
        /// Use this handler to take action when the user moves the mouse over your Dock Icon
        /// </remarks>
        /// <param name="e">MouseEventArgs data passed down from the dock manager</param>
        public void OnMouseMove(MouseEventArgs e)
        {

        }

        #endregion

        #region Properties
        // An instance of our settings page
        private ISettingsPage settingsPage;
        public ISettingsPage SettingsPage
        {
            get
            {
                if (settingsPage == null)
                {
                    settingsPage = new WidgetSettingsPage();
                }
                return settingsPage;
            }
        }

        // Our main content form
        private MainForm widgetMainForm;
        internal MainForm WidgetMainForm
        {
            get
            {
                if (widgetMainForm == null)
                {
                    widgetMainForm = new MainForm(_core);
                }
                return widgetMainForm;
            }
        }

        // Keep a reference to the core, in case we need any other core resources.
        public ICore _core;

        #endregion Properties

        #region Convenience methods
        internal static object GetFirstAssemblyAttribute(Type attributeType)
        {
            Assembly currentAssembly = Assembly.GetExecutingAssembly();
            object[] attributes = currentAssembly.GetCustomAttributes(attributeType, false);
            return attributes[0];
        }


        #endregion Convenience methods

    }
}